package chapt04.transform;
// SphereWorld.java
// OpenGL SuperBible
// Demonstrates an immersive 3D environment using actors and a camera.
// Program by Richard S. Wright Jr.

import javax.media.opengl.GL2;

import javax.media.opengl.glu.GLU;

import shared.*;

public class Transform
{
	static GLU glu = new GLU();
	
	static float yRot = 0.0f; // Rotation angle for animation
	
	// Draw a torus (doughnut), using the current 1D texture for light shading
	static void drawTorus(GL2 gl2, float mTransform[])
	{
		float majorRadius = 0.35f;
		float minorRadius = 0.15f;
		int numMajor = 40;
		int numMinor = 20;
		float objectVertex[] = new float[3];      // Vertex in object/eye space
		float transformedVertex[] = new float[3]; // New Transformed vertex
		double majorStep = 2.0f * Math.PI / numMajor;
		double minorStep = 2.0f * Math.PI / numMinor;
		int i, j;
		
		for(i = 0; i < numMajor; ++i)
		{
			double a0 = i * majorStep;
			double a1 = a0 + majorStep;
			float x0 = (float)Math.cos(a0);
			float y0 = (float)Math.sin(a0);
			float x1 = (float)Math.cos(a1);
			float y1 = (float)Math.sin(a1);
			
			gl2.glBegin(GL2.GL_TRIANGLE_STRIP);
			for(j = 0; j <= numMinor; ++j)
			{
				double b = j * minorStep;
				float c = (float)Math.cos(b);
				float r = minorRadius * c + majorRadius;
				float z = minorRadius * (float)Math.sin(b);
				
				// First point
				objectVertex[0] = x0 * r;
				objectVertex[1] = y0 * r;
				objectVertex[2] = z;
				M3D.transformVector3(transformedVertex, objectVertex, mTransform);
				gl2.glVertex3fv(transformedVertex, 0);
				
				// Second point
				objectVertex[0] = x1 * r;
				objectVertex[1] = y1 * r;
				objectVertex[2] = z;
				M3D.transformVector3(transformedVertex, objectVertex, mTransform);
				gl2.glVertex3fv(transformedVertex, 0);
			}
			gl2.glEnd();
		}
	}
	
	// This function does any needed initialization on the rendering
	// context.
	protected static void setup(GL2 gl2, int width, int height)
	{
		// Bluish background
		gl2.glClearColor(0.0f, 0.0f, 0.5f, 1.0f);
		
		// Draw everything as wire frame
		gl2.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE);
	}
	
	// Called to draw scene
	protected static void render(GL2 gl2, int w, int h)
	{
		float fAspect;
		
		// Prevent a divide by zero, when window is too short
		// (you can't make a window of zero width).
		if(h == 0)
			h = 1;
		
		gl2.glViewport(0, 0, w, h);
		
		fAspect = (float)w / (float)h;
		
		// Reset the coordinate system before modifying
		gl2.glMatrixMode(GL2.GL_PROJECTION);
		gl2.glLoadIdentity();
		
		// Set the clipping volume
		glu.gluPerspective(35.0f, fAspect, 1.0f, 50.0f);
		
		gl2.glMatrixMode(GL2.GL_MODELVIEW);
		gl2.glLoadIdentity();
		
		float transformationMatrix[] = new float[16]; // Storage for rotation matrix
		yRot += 0.5f;
		
		// Clear the window with current clearing color
		gl2.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
		
		// Build a rotation matrix
		M3D.rotationMatrix44(transformationMatrix, M3D.degToRad(yRot), 0.0f, 1.0f, 0.0f);
		transformationMatrix[12] = 0.0f;
		transformationMatrix[13] = 0.0f;
		transformationMatrix[14] = -2.5f;
		
		drawTorus(gl2, transformationMatrix);
		
		// Do the buffer swap
		gl2.glFlush();
	}
}